package com.yueke.gemini.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.util.JSONPObject;
import org.springframework.util.Assert;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

/**
 * Created by admin on 2017/10/21.
 */
public class JsonUtil {
    private static ObjectMapper mapper = null;

    static {
        mapper = new ObjectMapper();
        // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 允许key没有使用双引号的json
        mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        mapper.setDateFormat(format);
        // 驼峰转换
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        //配置不写value为null的key
        mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
        // 输出格式化
        mapper.configure(SerializationFeature.INDENT_OUTPUT, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    public static String toJson(Object obj) {
        Assert.notNull(obj);
        try {
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            System.out.println("序列化字符串错误;"+e);
        }
        return null;
    }

    public static byte[] toBytes(Object obj) {
        Assert.notNull(obj);
        try {
            return mapper.writeValueAsBytes(obj);
        } catch (JsonProcessingException e) {
            System.out.println("序列化字符串错误;"+e);
        }
        return null;
    }

    public static String toJson(Object key, Object value) {
        Assert.notNull(key);
        Map<Object, Object> map = new HashMap<>();
        map.put(key, value);
        try {
            return mapper.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            System.out.println("序列化字符串错误;"+ e);
        }
        return null;
    }

    public static <T> T fromJson(String jsonString, Class<T> clazz) {
        Assert.hasText(jsonString);
        try {
            return mapper.readValue(jsonString, clazz);
        } catch (IOException e) {
            System.out.println("反序列化字符串错误;"+e);
        }
        return null;
    }

    public static <L extends Collection<E>, E> L fromJson(String jsonString, Class<L> collectionClass, Class<E> elementClass) {
        Assert.hasText(jsonString);
        try {
            CollectionType type = mapper.getTypeFactory().constructCollectionType(collectionClass, elementClass);
            return mapper.readValue(jsonString, type);
        } catch (Exception e) {
            System.out.println("反序列化字符串错误:" + jsonString+" { }"+ e);
        }
        return null;
    }

    public static <T> T fromJson(String jsonString, TypeReference<T> typeRef) {
        Assert.hasText(jsonString);
        try {
            return mapper.readValue(jsonString, typeRef);
        } catch (Exception e) {
            System.out.println("反序列化字符串错误;"+e);
        }
        return null;
    }

    public static String toJsonP(String functionName, Object object) {
        Assert.hasText(functionName);
        Assert.notNull(object);
        return toJson(new JSONPObject(functionName, object));
    }

    public static <T> T convertValue(Object object, Class<T> clazz) {
        Assert.notNull(object);
        try {
            return mapper.convertValue(object, clazz);
        } catch (IllegalArgumentException e) {
            System.out.println("序列化对象错误;"+e);
        }
        return null;
    }
}
